%{
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<malloc.h>
#ifndef YYSTYPE
#define YYSTYPE double
#endif
int yylex();
extern int yyparse();
FILE* yyin;
void yyerror(const char* s);
struct id_struct
{
    char name[50];
    double value;
}id;
%}

%token ADD SUBSTACT MULTIPLY DIVIDE OPEN_PARENTHESIS CLOSE_PARENTHESIS NUMBER
%token ID EQUAL 
%left ADD SUBSTACT
%left MULTIPLY DIVIDE
%right UMINUS
%right EQUAL


%%


lines   :       lines expr ';' { printf("%f\n", $2); }
        |       lines ';'
        |
        ;
//TODO:完善表达式的规则
expr    :       term
        |       expr ADD term   { $$=$1+$3; }
        |       expr SUBSTACT term  {$$=$1-$3;}
        |       ID  {$$=id.value;}
        |       ID EQUAL expr{
                                $$=$3;
                                id.value=$3;
                            }
        ;
term    :       factor
        |       term MULTIPLY factor  {$$=$1*$3;}
        |       term DIVIDE factor  {
                                        if($3==0.0)
                                            yyerror("divide by zero!");
                                        else
                                            $$=$1/$3;
                                    }
        ;
factor  :       NUMBER {$$=$1;}
        |       OPEN_PARENTHESIS expr CLOSE_PARENTHESIS {$$=$2;}
        |       SUBSTACT factor %prec UMINUS {$$=-$2;}
        ;


%%

// programs section

int yylex()
{
    int t;
    while(1){
        t=getchar();
        if(t==' '||t=='\t'||t=='\n'){
            //do noting
        }else if(isdigit(t)){
            yylval=0;
            while(isdigit(t)){
                yylval=yylval*10+(t-'0');
                t=getchar();
            }
            ungetc(t,stdin);
            return NUMBER;
        }else if(t=='+'){
            return ADD;
        }else if(t=='-'){
            return SUBSTACT;
        }
        else if(t=='*'){
            return MULTIPLY;
        }else if(t=='/')
        {
            return DIVIDE;
        }else if(t=='('){
            return OPEN_PARENTHESIS;
       }else if(t==')'){
            return CLOSE_PARENTHESIS;
        }else if(isalpha(t)){
            int index=0;
            while(isalpha(t)){
                id.name[index++]=t;
                t=getchar();
            }
            id.name[index]='\0';
            ungetc(t,stdin);
            return ID;
        }else if(t=='='){
            return EQUAL;
        }
        else{
            return t;
        }
    }
}

int main(void)
{
    yyin=stdin;
    do{
        yyparse();
    }while(!feof(yyin));
    return 0;
}
void yyerror(const char* s){
    fprintf(stderr,"Parse error: %s\n",s);
    exit(1);
}
